package botcraft.gui;

import java.awt.Component;
import java.awt.DisplayMode;
import java.awt.FlowLayout;
import java.awt.GraphicsDevice;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.ListCellRenderer;

public class Settings extends GuiApplication {
	private static final Logger LOGGER = Logger.getLogger(Settings.class.getName());
	
	public static void main(final String[] arguments) {
		try {
			GuiApplication.invoke(new Settings());
		} catch (final InterruptedException e) {
		} catch (final InvocationTargetException e) {
			LOGGER.log(Level.SEVERE, "Error invoking settings", e);
			JOptionPane.showMessageDialog(null, "Error invoking settings", e.getMessage(), JOptionPane.ERROR_MESSAGE);
		}
	}
	
	@Override
	public void run() {
		final JFrame frame = new JFrame();
		frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
		final JTabbedPane tabbedPane = new JTabbedPane();
		final JPanel general = new JPanel();
		general.setLayout(new GridLayout(0, 2));
		general.add(new JLabel(getResourceBundle().getString("locale"), JLabel.RIGHT));
		final JComboBox locales = new JComboBox();
		for (Locale locale : configuration.getLocales())
			locales.addItem(locale);
		locales.setSelectedItem(configuration.getLocale());
		locales.setEnabled(locales.getItemCount() > 1);
		final ListCellRenderer localesRenderer = locales.getRenderer();
		locales.setRenderer(new ListCellRenderer() {
			@Override
			public Component getListCellRendererComponent(final JList list, final Object item, final int index, final boolean selected, final boolean focused) {
				return localesRenderer.getListCellRendererComponent(list, ((Locale) item).getDisplayName((Locale) item), index, selected, focused);
			}
		});
		general.add(locales);
		tabbedPane.addTab(getResourceBundle().getString("general"), general);
		final JPanel video = new JPanel();
		video.setLayout(new GridLayout(0, 2));
		video.add(new JLabel(getResourceBundle().getString("screen"), JLabel.RIGHT));
		final JComboBox screens = new JComboBox();		
		for (GraphicsDevice screen : configuration.getScreens())
			screens.addItem(screen);
		screens.setSelectedItem(configuration.getScreen());
		screens.setEnabled(screens.getItemCount() > 1);
		final ListCellRenderer screensRenderer = screens.getRenderer();
		screens.setRenderer(new ListCellRenderer() {
			@Override
			public Component getListCellRendererComponent(final JList list, final Object item, final int index, final boolean selected, final boolean focused) {
				return screensRenderer.getListCellRendererComponent(list, ((GraphicsDevice) item).getIDstring(), index, selected, focused);
			}
		});
		video.add(screens);	
		video.add(new JLabel(getResourceBundle().getString("displayMode"), JLabel.RIGHT));
		final JComboBox displayModes = new JComboBox();
		for (DisplayMode displayMode : configuration.getDisplayModes())
			displayModes.addItem(displayMode);
		displayModes.setSelectedItem(configuration.getDisplayMode());
		final ListCellRenderer displayModesRenderer = displayModes.getRenderer();
		displayModes.setRenderer(new ListCellRenderer() {
			@Override
			public Component getListCellRendererComponent(final JList list, final Object item, final int index, final boolean selected, final boolean focused) {
				final DisplayMode displayMode = (DisplayMode) item;
				return displayModesRenderer.getListCellRendererComponent(list, displayMode.getWidth() + " x" + displayMode.getHeight() + " pixels" +
						((displayMode.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI) ? "" : (", " + displayMode.getBitDepth() + "-bit color")) +
						((displayMode.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN) ? "" : (", " + displayMode.getRefreshRate() + " Hz")), index,
						selected, focused);
			}
		});
		video.add(displayModes);
		tabbedPane.addTab(getResourceBundle().getString("video"), video);
		frame.add(tabbedPane);
		final JPanel buttons = new JPanel();
		buttons.setLayout(new FlowLayout());
		final JButton save = new JButton(getResourceBundle().getString("save"));
		buttons.add(save);
		final JButton cancel = new JButton(getResourceBundle().getString("cancel"));
		buttons.add(cancel);
		frame.add(buttons);
		frame.pack();
		locales.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent actionEvent) {
				final Locale locale = (Locale) locales.getSelectedItem();
				if (locale != null)
					configuration.setLocale(locale);
			}
		});
		screens.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent actionEvent) {
				final GraphicsDevice screen = (GraphicsDevice) screens.getSelectedItem();
				if (screen != null) {
					configuration.setScreen(screen);
					final ActionListener[] actionListeners = displayModes.getActionListeners();
					for (ActionListener actionListener : actionListeners)
						displayModes.removeActionListener(actionListener);
					displayModes.removeAllItems();
					for (DisplayMode displayMode : configuration.getDisplayModes())
						displayModes.addItem(displayMode);
					displayModes.setSelectedItem(configuration.getDisplayMode());
					displayModes.setEnabled(displayModes.getItemCount() > 1);
					for (ActionListener actionListener : actionListeners)
						displayModes.addActionListener(actionListener);
				}
			}
		});
		displayModes.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent actionEvent) {			
				final DisplayMode displayMode = (DisplayMode) displayModes.getSelectedItem();
				if (displayMode != null)
					configuration.setDisplayMode(displayMode);
			} 
		});
		save.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent actionEvent) {
				frame.dispose();
				try {
					configuration.save();
				} catch (final BackingStoreException e) {
					LOGGER.log(Level.WARNING, "Error saving settings", e);
					JOptionPane.showMessageDialog(frame, "Error saving settings", e.getMessage(), JOptionPane.WARNING_MESSAGE);
				}
			}
		});
		cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent actionEvent) {
				frame.dispose();
			}
		});
		frame.setVisible(true);
		frame.requestFocusInWindow();
	}
}
